package com.xps.and.yuntong;

import android.annotation.TargetApi;
import android.app.Activity;
import android.app.Application;
import android.app.Notification;
import android.app.NotificationManager;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.os.PowerManager;
import android.support.annotation.RequiresApi;
import android.support.multidex.MultiDexApplication;
import android.text.TextUtils;
import android.util.Log;

//import com.baidu.trace.api.entity.LocRequest;
//import com.baidu.trace.api.entity.OnEntityListener;
//import com.baidu.trace.api.track.OnTrackListener;
//import com.baidu.trace.model.OnTraceListener;
//import com.baidu.trace.model.ProcessOption;
//import com.jude.utils.JUtils;
//import com.xps.and.driverside.receiver.TrackReceiver;

import com.baidu.mapapi.SDKInitializer;
import com.baidu.trace.LBSTraceClient;
import com.baidu.trace.Trace;
import com.baidu.trace.api.entity.LocRequest;
import com.baidu.trace.api.entity.OnEntityListener;
import com.baidu.trace.api.fence.FenceAlarmPushInfo;
import com.baidu.trace.api.fence.MonitoredAction;
import com.baidu.trace.api.track.LatestPoint;
import com.baidu.trace.api.track.LatestPointRequest;
import com.baidu.trace.api.track.LatestPointResponse;
import com.baidu.trace.api.track.OnTrackListener;
import com.baidu.trace.model.OnTraceListener;
import com.baidu.trace.model.ProcessOption;
import com.baidu.trace.model.PushMessage;
import com.baidu.trace.model.StatusCodes;
import com.baidu.trace.model.TraceLocation;
import com.baidu.trace.model.TransportMode;
import com.xps.and.yuntong.Ui.LoginActivity;
import com.xps.and.yuntong.Utils.BaiduCommonUtil;
import com.xps.and.yuntong.Utils.CustomCrashWriter;
import com.xps.and.yuntong.Utils.GlobalPositionInfo;
import com.xps.and.yuntong.baidu.CommonUtil;
import com.xps.and.yuntong.receiver.TrackReceiver;
import com.xps.and.yuntong.service.RemoteService;
import com.iflytek.cloud.Setting;
import com.iflytek.cloud.SpeechUtility;
import com.jude.utils.JUtils;
import com.squareup.leakcanary.LeakCanary;
import com.umeng.socialize.PlatformConfig;
import com.umeng.socialize.UMShareAPI;
import com.wenming.library.LogReport;
import com.wenming.library.upload.email.EmailReporter;

import java.io.File;
import java.lang.ref.SoftReference;
import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicInteger;

import cn.jpush.android.api.JPushInterface;
import io.reactivex.Flowable;

@RequiresApi(api = Build.VERSION_CODES.CUPCAKE)
//public class App extends MultiDexApplication implements Handler.Callback, Application.ActivityLifecycleCallbacks {
public class App extends MultiDexApplication implements Handler.Callback, Application.ActivityLifecycleCallbacks{
//    public static long serviceId = 130778;
    public static long serviceId = 157032;
    //线下鹰眼
    // public static long serviceId = 147998;
    private static App INSTANCE;
    public String mAppDir;
    public String mPicturesDir;
    public String mFilesDir;
    public GlobalPositionInfo globalPositionInfo;
    public Context mContext = null;
    public SharedPreferences trackConf = null;
    /**
     * 轨迹客户端
     */
    public LBSTraceClient mClient = null;
    /**
     * 轨迹服务
     */
    public Trace mTrace = null;
    /**
     * Entity标识
     */
    public String entityName = "myTrace";
    public boolean isRegisterReceiver = false;
    /**
     * 服务是否开启标识
     */
    public boolean isTraceStarted = false;
    /**
     * 采集是否开启标识
     */
    public boolean isGatherStarted = false;
    /**
     * 轨迹服务监听器
     */
    /**
     * 鹰眼可用标志
     */
    //public boolean isLocatActive;
    ArrayList<SoftReference<Activity>> activitiesCollected = new ArrayList<>();
    Handler handler = null;
    ProcessOption processOption;
    private String TAG = "com.App";
    private AtomicInteger mSequenceGenerator = new AtomicInteger();
    private LocRequest locRequest = null;
    private NotificationManager notificationManager = null;
    private PowerManager powerManager = null;
    private PowerManager.WakeLock wakeLock = null;
    private TrackReceiver trackReceiver = null;
    private OnTraceListener traceListener = null;
    /**
     * 轨迹监听器(用于接收纠偏后实时位置回调)
     */
    private OnTrackListener trackListener = null;
    /**
     * Entity监听器(用于接收实时定位回调)
     */
    private OnEntityListener entityListener = null;
    private RealTimeLocRunnable realTimeLocRunnable = null;
    private Notification notification = null;
    private int notifyId = 0;




    public static App getInstance() {
        return INSTANCE;
    }
//SpeechUtility.createUtility(this, "appid=" + "5a406020");
    @Override
    public void onCreate() {
        super.onCreate();
        initAppDir();

        mContext = getApplicationContext();

        globalPositionInfo = new GlobalPositionInfo(this);
        registerActivityLifecycleCallbacks(this);
        INSTANCE = this;
        handler = new Handler(getMainLooper(), this);
        //百度地图
        SDKInitializer.initialize(this);
        //工具库
        JUtils.initialize(this);

        //讯飞语音
        SpeechUtility.createUtility(this, "appid=" + "5a406020");
        Setting.setShowLog(false);
        //友盟分享
        UMShareAPI.get(this);

        PlatformConfig.setWeixin(Constants.APP_ID, Constants.SECRET);
        PlatformConfig.setQQZone("1105809249", "aIbLupLQui98VUyu");
        //Config.DEBUG = true; // 开启可以看到配置信息
        //百度鹰眼
        if (!"com.baidu.track:remote".equals(BaiduCommonUtil.getCurProcessName(this))) {
            mContext = getApplicationContext();
            entityName = CommonUtil.getImei(this);
            SDKInitializer.initialize(mContext);
            initNotification();
            mClient = new LBSTraceClient(mContext);
            mTrace = new Trace(serviceId, entityName);
            mTrace.setNotification(notification);
            trackConf = getSharedPreferences("track_conf", MODE_PRIVATE);
            locRequest = new LocRequest(serviceId);
            clearTraceStatus();
        }

        //LeakCanary
        if (LeakCanary.isInAnalyzerProcess(this)) {
            // This process is dedicated to LeakCanary for heap analysis.
            // You should not init your app in this process.
            return;
        }

        LeakCanary.install(this);

        initCrashReport();
        //LogReport.getInstance().upload(this);

        //--------------------鹰眼开始
        powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
        notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

        processOption = new ProcessOption();
        processOption.setNeedDenoise(true);
        processOption.setTransportMode(TransportMode.driving);//行驶模式 汽车
        processOption.setNeedDenoise(true);//去燥
        processOption.setNeedMapMatch(true);//绑路
        processOption.setNeedVacuate(true);//抽稀
        processOption.setRadiusThreshold(55);
        //--------------------鹰眼结束
    }

    /**
     * 准备鹰眼
     */
    public void prepareYingYan() {
//        SharedPreferences sp = JUtils.getSharedPreference();
//        if (TextUtils.isEmpty(sp.getString("access_token", ""))) return;
//        String driver = JUtils.getSharedPreference().getString("driver_id", "");
//        mTrace.setEntityName("driver_" + driver);
//        Log.e(TAG, "driver" + driver);
        Log.e("111","鹰眼走了吗");
        entityName = mTrace.getEntityName();
        mClient.setInterval(com.xps.and.yuntong.baidu.Constants.DEFAULT_GATHER_INTERVAL, com.xps.and.yuntong.baidu.Constants.DEFAULT_PACK_INTERVAL);
        startRealTimeLoc(com.xps.and.yuntong.baidu.Constants.LOC_INTERVAL);
        starTrackServer();
        initListener();
    }

    private void initCrashReport() {
        LogReport.getInstance()
                .setCacheSize(30 * 1024 * 1024)//支持设置缓存大小，超出后清空
                .setLogDir(getApplicationContext(), "sdcard/" + this.getString(this.getApplicationInfo().labelRes) + "/")//定义路径为：sdcard/[app name]/
                .setWifiOnly(false)//设置只在Wifi状态下上传，设置为false为Wifi和移动网络都上传
                .setLogSaver(new CustomCrashWriter(getApplicationContext()))//支持自定义保存崩溃信息的样式
                //.setEncryption(new AESEncode()) //支持日志到AES加密或者DES加密，默认不开启
                .init(getApplicationContext());
        initEmailReporter();
    }

    public void exitApp() {
        Flowable.just(activitiesCollected).flatMap(Flowable::fromIterable)
                .filter(softAct -> softAct.get() != null && (!softAct.get().isFinishing() || !softAct.get().isDestroyed()))
                .forEach(softAct -> softAct.get().finish());
        doClearCache();
    }

    public void starTrackServer() {
        if (!isTraceStarted) {
            mClient.startTrace(mTrace, traceListener);
            Log.e("startTrace", "startTrace");
            if (!isGatherStarted) {
                mClient.startGather(traceListener);
                Log.e("startTrace", "startGather");
            }
        }
        boolean login = JUtils.getSharedPreference().getBoolean("User_Login", false);
        if (login) {
            isTraceStarted = true;
            isGatherStarted = true;
        }
    }

    public void stopTrackServer() {
        Log.e("stopTrace", "stopTrackServer");
        if (isTraceStarted) {
            mClient.stopTrace(mTrace, traceListener);
            Log.e("stopTrace", "stopTrace");
            if (isGatherStarted) {
                mClient.stopGather(traceListener);
                Log.e("stopTrace", "stopGather");

            }
        }
    }


    /**
     * 使用EMAIL发送日志
     */
    private void initEmailReporter() {
        EmailReporter email = new EmailReporter(this);
        email.setReceiver("15811139099@163.com");//收件人
        email.setSender("790928421@qq.com");//发送人邮箱
        email.setSendPassword("yfkvycwrtiicbcbd");//邮箱的客户端授权码，注意不是邮箱密码
        email.setSMTPHost("smtp.qq.com");//SMTP地址
        email.setPort("465");//SMTP 端口
        LogReport.getInstance().setUploadType(email);
    }

    public GlobalPositionInfo getGloPosinfo() {
        return globalPositionInfo;
    }


    public void stopRealTimeLoc() {
        if (null != handler && null != realTimeLocRunnable) {
            handler.removeCallbacks(realTimeLocRunnable);
        }
    }

    private void initAppDir() {
        File file = getExternalFilesDir(null);
        if (!file.exists()) {
            file.mkdirs();
        }

        mAppDir = file.getAbsolutePath();

        file = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
        if (!file.exists()) {
            file.mkdirs();
        }

        mPicturesDir = file.getAbsolutePath();

        file = getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS);
        if (!file.exists()) {
            file.mkdirs();
        }

        mFilesDir = file.getAbsolutePath();
    }

    /**
     * 查询当前位置  查询 查询 查询
     */
    public void getCurrentLocation(OnEntityListener entityListener, OnTrackListener trackListener) {
        // 网络连接正常，开启服务及采集，则查询纠偏后实时位置；否则进行实时定位
        if (JUtils.isNetWorkAvilable()
                && trackConf.contains("is_trace_started")
                && trackConf.contains("is_gather_started")
                && trackConf.getBoolean("is_trace_started", false)
                && trackConf.getBoolean("is_gather_started", false)) {
            LatestPointRequest request = new LatestPointRequest(getTag(), serviceId, entityName);
            request.setProcessOption(processOption);
            mClient.queryLatestPoint(request, trackListener);
            Log.e(TAG, "getCurrentLocation:" + "LatestPointRequest");
        } else {
            mClient.queryRealTimeLoc(locRequest, entityListener);
            Log.e(TAG, "getCurrentLocation:" + "queryRealTimeLoc");
        }

    }

    @TargetApi(16)
    private void initNotification() {
        Notification.Builder builder = new Notification.Builder(this);
        builder.setSmallIcon(R.mipmap.logo);
        builder.setContentTitle("百度鹰眼");
        builder.setContentText("百度鹰眼服务正在运行...");
        notification = builder.build(); // 获取构建好的Notification
        notification.defaults = Notification.DEFAULT_SOUND; //设置为默认的声音
    }

    /**
     * 清除Trace状态：初始化app时，判断上次是正常停止服务还是强制杀死进程，根据trackConf中是否有is_trace_started字段进行判断。
     * <p>
     * 停止服务成功后，会将该字段清除；若未清除，表明为非正常停止服务。
     */
    private void clearTraceStatus() {
        if (trackConf.contains("is_trace_started") || trackConf.contains("is_gather_started")) {
            SharedPreferences.Editor editor = trackConf.edit();
            editor.remove("is_trace_started");
            editor.remove("is_gather_started");
            editor.apply();
        }
    }

    public int getTag() {
        return mSequenceGenerator.incrementAndGet();
    }

    @Override
    public boolean handleMessage(Message msg) {
        return false;
    }

    private void initListener() {

        /**
         * 轨迹监听器
         * */
        trackListener = new OnTrackListener() {
            /**
             * 查询最新轨迹点回调
             * */
            @Override
            public void onLatestPointCallback(LatestPointResponse response) {
                Log.e(TAG, "trackListener" + response.toString());
                if (StatusCodes.SUCCESS != response.getStatus()) {
                    //isLocatActive = false;
                    return;
                }

                LatestPoint point = response.getLatestPoint();
                if (null == point || BaiduCommonUtil.isZeroPoint(point.getLocation().getLatitude(), point.getLocation()
                        .getLongitude())) {
                    //isLocatActive = false;
                    return;
                }

                //isLocatActive = true;

            }
        };

        /**
         * 实时定位回调接口
         * */
        entityListener = new OnEntityListener() {
            @Override
            public void onReceiveLocation(TraceLocation location) {
                Log.e("trackListener", "entityListener:" + location.toString());
                if (StatusCodes.SUCCESS != location.getStatus() || BaiduCommonUtil.isZeroPoint(location.getLatitude(),
                        location.getLongitude())) {
                    // isLocatActive = false;
                    return;
                }
                //isLocatActive = true;
            }
        };

        traceListener = new OnTraceListener() {

            /**
             * 绑定服务回调接口
             *
             * @param errorNo 状态码
             * @param message 消息
             *                <p>
             *                <pre>0：成功 </pre>
             *                <pre>1：失败</pre>
             */
            @Override
            public void onBindServiceCallback(int errorNo, String message) {
                Log.e("trackListener", String.format("onBindServiceCallback, errorNo:%d, message:%s ", errorNo, message));
            }


            /**
             * 开启服务回调接口
             *
             * @param errorNo 状态码
             * @param message 消息
             *                <p>
             *                <pre>0：成功 </pre>
             *                <pre>10000：请求发送失败</pre>
             *                <pre>10001：服务开启失败</pre>
             *                <pre>10002：参数错误</pre>
             *                <pre>10003：网络连接失败</pre>
             *                <pre>10004：网络未开启</pre>
             *                <pre>10005：服务正在开启</pre>
             *                <pre>10006：服务已开启</pre>
             */
            @Override
            public void onStartTraceCallback(int errorNo, String message) {
                if (StatusCodes.SUCCESS == errorNo || StatusCodes.START_TRACE_NETWORK_CONNECT_FAILED <= errorNo) {
                    isTraceStarted = true;
                    SharedPreferences.Editor editor = trackConf.edit();
                    editor.putBoolean("is_trace_started", true);
                    editor.apply();
                    registerReceiver();
                    Log.e("trackListener", "trace was started");
                }
                Log.e("trackListener", String.format("onStartTraceCallback, errorNo:%d, message:%s ", errorNo, message));
            }

            /**
             * 停止服务回调接口
             *
             * @param errorNo 状态码
             * @param message 消息
             *                <p>
             *                <pre>0：成功</pre>
             *                <pre>11000：请求发送失败</pre>
             *                <pre>11001：服务停止失败</pre>
             *                <pre>11002：服务未开启</pre>
             *                <pre>11003：服务正在停止</pre>
             */
            @Override
            public void onStopTraceCallback(int errorNo, String message) {
                if (StatusCodes.SUCCESS == errorNo || StatusCodes.CACHE_TRACK_NOT_UPLOAD == errorNo) {
                    isTraceStarted = false;
                    // 停止成功后，直接移除is_trace_started记录（便于区分用户没有停止服务，直接杀死进程的情况）
                    SharedPreferences.Editor editor = trackConf.edit();
                    editor.remove("is_trace_started");
                    editor.remove("is_gather_started");
                    editor.apply();
                    unregisterPowerReceiver();
                }
                Log.e("trackListener", String.format("onStopTraceCallback, errorNo:%d, message:%s ", errorNo, message));
            }

            /**
             * 开启采集回调接口
             *
             * @param errorNo 状态码
             * @param message 消息
             *                <p>
             *                <pre>0：成功</pre>
             *                <pre>12000：请求发送失败</pre>
             *                <pre>12001：采集开启失败</pre>
             *                <pre>12002：服务未开启</pre>
             */
            @Override
            public void onStartGatherCallback(int errorNo, String message) {
                if (StatusCodes.SUCCESS == errorNo || StatusCodes.GATHER_STARTED == errorNo) {
                    isGatherStarted = true;
                    SharedPreferences.Editor editor = trackConf.edit();
                    editor.putBoolean("is_gather_started", true);
                    editor.apply();
                    Log.e("trackListener", "gather was started");
                }
                Log.e("trackListener", String.format("onStartGatherCallback, errorNo:%d, message:%s ", errorNo, message));
            }

            /**
             * 停止采集回调接口
             *
             * @param errorNo 状态码
             * @param message 消息
             *                <p>
             *                <pre>0：成功</pre>
             *                <pre>13000：请求发送失败</pre>
             *                <pre>13001：采集停止失败</pre>
             *                <pre>13002：服务未开启</pre>
             */
            @Override
            public void onStopGatherCallback(int errorNo, String message) {
                if (StatusCodes.SUCCESS == errorNo || StatusCodes.GATHER_STOPPED == errorNo) {
                    isGatherStarted = false;
                    SharedPreferences.Editor editor = trackConf.edit();
                    editor.remove("is_gather_started");
                    editor.apply();
                }
                Log.e("trackListener", String.format("onStopGatherCallback, errorNo:%d, message:%s ", errorNo, message));
            }

            /**
             * 推送消息回调接口
             *
             * @param messageType 状态码
             * @param pushMessage 消息
             *                    <p>
             *                    <pre>0x01：配置下发</pre>
             *                    <pre>0x02：语音消息</pre>
             *                    <pre>0x03：服务端围栏报警消息</pre>
             *                    <pre>0x04：本地围栏报警消息</pre>
             *                    <pre>0x05~0x40：系统预留</pre>
             *                    <pre>0x41~0xFF：开发者自定义</pre>
             */
            @Override
            public void onPushCallback(byte messageType, PushMessage pushMessage) {
                if (messageType < 0x03 || messageType > 0x04) {
                    JUtils.Toast(pushMessage.getMessage());
                    return;
                }
                FenceAlarmPushInfo alarmPushInfo = pushMessage.getFenceAlarmPushInfo();
                if (null == alarmPushInfo) {
                    JUtils.Toast(String.format("onPushCallback, messageType:%d, messageContent:%s ", messageType,
                            pushMessage));
                    return;
                }
                StringBuffer alarmInfo = new StringBuffer();
                alarmInfo.append("您于")
                        .append(CommonUtil.getHMS(alarmPushInfo.getCurrentPoint().getLocTime() * 1000))
                        .append(alarmPushInfo.getMonitoredAction() == MonitoredAction.enter ? "进入" : "离开")
                        .append(messageType == 0x03 ? "云端" : "本地")
                        .append("围栏：").append(alarmPushInfo.getFenceName());

                Notification notification = new Notification.Builder(App.this)
                        .setContentTitle(getResources().getString(R.string.alarm_push_title))
                        .setContentText(alarmInfo.toString())
                        .setSmallIcon(R.mipmap.logo)
                        .setWhen(System.currentTimeMillis()).build();
                notificationManager.notify(notifyId++, notification);
            }
        };
    }

    private void registerReceiver() {
        if (isRegisterReceiver) {
            return;
        }

        if (null == wakeLock) {
            wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "track upload");
        }

        if (null == trackReceiver) {
            trackReceiver = new TrackReceiver(wakeLock);
        }

        IntentFilter filter = new IntentFilter();
        filter.addAction(Intent.ACTION_SCREEN_OFF);
        filter.addAction(Intent.ACTION_SCREEN_ON);
        filter.addAction(Intent.ACTION_USER_PRESENT);
        filter.addAction(StatusCodes.GPS_STATUS_ACTION);
        registerReceiver(trackReceiver, filter);
        isRegisterReceiver = true;
    }

    private void unregisterPowerReceiver() {
        if (!isRegisterReceiver) {
            return;
        }
        if (null != trackReceiver) {
            unregisterReceiver(trackReceiver);
        }
        isRegisterReceiver = false;
    }

    public void startRealTimeLoc(int interval) {
        realTimeLocRunnable = new RealTimeLocRunnable(interval);
        handler.post(realTimeLocRunnable);
    }

    void doClearCache() {
        clearUser();
        Intent intent = new Intent(this, LoginActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.putExtra("zhanghao", "1");
        startActivity(intent);
        Intent Serviceintent = new Intent(this, RemoteService.class);
        stopService(Serviceintent);
        JPushInterface.setAliasAndTags(this, "", null, null);
    }


    void clearUser() {
        SharedPreferences sp = JUtils.getSharedPreference();
        SharedPreferences.Editor spEd = sp.edit();
//        spEd.putString("access_token", "");
        spEd.putInt("user_id", -1);
        spEd.putInt("sex", -1);
        spEd.putInt("driver_id", -1);
        spEd.putString("name", "");
        spEd.putString("mobile_phone", "");
        spEd.putString("head_img", "");
        spEd.putString("balance", "");
        spEd.putString("idcard_id", "");
        spEd.putString("password", "");
//        spEd.putString("name", "");
//        spEd.putString("idcard_id", "");
//        spEd.putString("head_img", "");
//        spEd.putString("photo_url", "");
//        spEd.putString("driver_license", "");
//        spEd.putString("driving_license", "");
//        spEd.putString("idcard_up", "");
//        spEd.putString("idcard_down", "");
        spEd.apply();
        stopTrackServer();
    }

    @Override
    public void onActivityCreated(Activity activity, Bundle savedInstanceState) {

    }

    @Override
    public void onActivityStarted(Activity activity) {
        activitiesCollected.add(new SoftReference<Activity>(activity));
    }

    @Override
    public void onActivityResumed(Activity activity) {

    }

    @Override
    public void onActivityPaused(Activity activity) {

    }

    @Override
    public void onActivityStopped(Activity activity) {

    }

    @Override
    public void onActivitySaveInstanceState(Activity activity, Bundle outState) {

    }

    @Override
    public void onActivityDestroyed(Activity activity) {

    }

    /**
     * 实时定位任务
     */
    private class RealTimeLocRunnable implements Runnable {

        private int interval = 0;

        private RealTimeLocRunnable(int interval) {
            this.interval = interval;
        }

        @Override
        public void run() {
            getCurrentLocation(entityListener, trackListener);
            handler.postDelayed(this, interval * 1000);
        }
    }

}